﻿using System;
using System.Collections.Generic;
using System.Linq;
using TopVisionLog;
using System.Threading;
using System.Threading.Tasks;

namespace TopVisionVideoStream
{
    /// <summary>
    /// 集采设备管理器
    /// </summary>
    class CaptureManager
    {
        /// <summary>
        /// 当前摄像头索引
        /// </summary>
        public static int CurCamIndex;
        /// <summary>
        /// 当前扬声器索引
        /// </summary>
        public static int CurSpeakerIndex;
        /// <summary>
        /// 当前麦克风索引
        /// </summary>
        public static int CurMicIndex;
        /// <summary>
        /// ["AUTO"]["1080p"]["720p"]["480p"]["240p"]
        /// </summary>
        public const string DefultResolution = "AUTO";

        public static string CurResolution = DefultResolution;

        public static string[] Resolutions = new string[] { "AUTO", "1080p", "720p", "480p", "240p" };

        // 音频
        //public static List<AudioDevice> PlaybackDevices => TVMixer.Instance.PlaybackDevices;

        public static bool SpeakerErr = true;

        //public static List<AudioDevice> RecordDevices => TVMixer.Instance.RecordDevices;

        public static bool MicErr = true;

        //public static AudioDevice CurrentRecordDevice;

        //public static AudioDevice CurrentPlaybackDevice;

        // 视频
        //public static List<CameraDevice> WebCameras => VideoCapture.CaptureManager.CameraDevices;

        //public static CameraDevice CurrentCamera;

        public static List<string> CameraNames = new List<string>();

        public static List<string> SpeakerNames = new List<string>();

        public static List<string> MicrophoneNames = new List<string>();

        /// <summary>
        /// 回声抑制
        /// </summary>
        public static bool EC = true;
        /// <summary>
        /// 噪音消除
        /// </summary>
        public static bool NS = true;
        /// <summary>
        /// 自动增益
        /// </summary>
        public static bool AGC = false;

        // 音频参数
        private static int micState = 2;

        private static int micVolume = 50;

        private static int spkState = 2;

        private static int spkVolume = 100;

        ///// <summary>
        ///// 扬声器音量
        ///// </summary>
        //public static int SpeakerVolume
        //{
        //    get { return spkVolume; }
        //    set
        //    {
        //        spkVolume = value;
        //        if (!SpeakerErr)
        //            CurrentPlaybackDevice.Volume = 65535 * spkVolume / 100;
        //    }
        //}

        //public static bool SpeakerMute
        //{
        //    get { return CurrentPlaybackDevice.Mute; }
        //    set
        //    {
        //        if (!SpeakerErr)
        //            CurrentPlaybackDevice.Mute = value;
        //    }
        //}

        ///// <summary>
        ///// 麦克风音量
        ///// </summary>
        //public static int MicrophoneLevel
        //{
        //    get { return micVolume; }
        //    set
        //    {
        //        micVolume = value;
        //        if (!MicErr)
        //            CurrentRecordDevice.Volume = 65535 * micVolume / 100;
        //    }
        //}

        ///// <summary>
        ///// 麦克风静音
        ///// </summary>
        //public static bool MicrophoneMute
        //{
        //    get { return CurrentRecordDevice.Mute; ; }
        //    set
        //    {
        //        if (!MicErr)
        //            CurrentRecordDevice.Mute = value;
        //    }
        //}

        private static bool isLoadingCamera = true;
        private static bool isLoadingAudio = true;

        public static bool IsLoadingCaptureList => isLoadingCamera | isLoadingAudio;

        /// <summary>
        /// 初始化
        /// </summary>
        public static void Init()
        {
            TVLog.WriteLine("初始化采集设备>>>>>>");

            //GetCaptures();

            GetCaptureList();

            OcxApi.GetVideoDeviceListResultWebEvent += (o, e) =>
            {
                try
                {
                    TVLog.WriteLine("VideoDevices:===========================");

                    CameraNames = e.pDeviceName.Split('|').ToList();

                    isLoadingCamera = false;

                    string log = "";

                    for (int i = 0; i < CameraNames.Count; i++)
                    {
                        if (CameraNames[i] == "")
                        {
                            CameraNames.RemoveAt(i);

                            i--;
                        }
                        else
                        {
                            TVLog.WriteLine(CameraNames[i]);
                        }
                    }

                    TVLog.WriteLine("VideoDevices:===========================");
                }
                catch (Exception ex)
                {
                    TVLog.WriteLine("ERR GetVideoDeviceListResultWebEvent " + ex.Message);

                    isLoadingCamera = false;
                }
            };

            OcxApi.GetAudioDeviceListResultWebEvent += (o, e) =>
            {
                try
                {
                    TVLog.WriteLine("AudioDevices:===========================");
                    TVLog.WriteLine("Microphone:===========================");

                    MicrophoneNames = e.pRecDevNames.Split('|').ToList();

                    SpeakerNames = e.pPlayoutDevNames.Split('|').ToList();

                    isLoadingAudio = false;

                    string log = "";

                    for (int i = 0; i < MicrophoneNames.Count; i++)
                    {
                        if (MicrophoneNames[i].Contains("\u0001"))
                            MicrophoneNames[i] = MicrophoneNames[i].Substring(0, MicrophoneNames[i].IndexOf("\u0001"));

                        MicrophoneNames[i] = MicrophoneNames[i].Trim();

                        TVLog.WriteLine(MicrophoneNames[i]);
                    }

                    TVLog.WriteLine("Speaker:===========================");

                    for (int i = 0; i < SpeakerNames.Count; i++)
                    {
                        if (SpeakerNames[i].Contains("\u0001"))
                            SpeakerNames[i] = SpeakerNames[i].Substring(0, SpeakerNames[i].IndexOf("\u0001"));

                        SpeakerNames[i] = SpeakerNames[i].Trim();

                        TVLog.WriteLine(SpeakerNames[i]);
                    }

                    TVLog.WriteLine("AudioDevices::===========================");
                }
                catch (Exception ex)
                {
                    TVLog.WriteLine("ERR GetAudioDeviceListResultWebEvent " + ex.Message);

                    isLoadingAudio = false;
                }
            };

            TimeoutCheck();
        }

        private async static void TimeoutCheck(int timeout = 6000)
        {
            await Task.Delay(timeout);
            if (IsLoadingCaptureList)
            {
                isLoadingCamera = false;
                isLoadingAudio = false;
            }
        }

        public async static void GetCaptureList()
        {
            isLoadingCamera = true;
            isLoadingAudio = true;
            await Task.Delay(1000);
            Configuration.Core.GetVideoDeviceList();
            Configuration.Core.GetAudioDeviceList();
        }

        //public static void UpdateDeviceList()
        //{
        //    //Configuration.Core.GetVideoDeviceList();
        //    //Configuration.Core.GetAudioDeviceList();

        //    TVMixer.Instance.Update();
        //    VideoCapture.CaptureManager.Update();
        //}

        //public static void UpdateCameraList()
        //{
        //    VideoCapture.CaptureManager.Update();
        //}

        //public static bool SetCamera(CameraDevice camera)
        //{
        //    int index = -1;
        //    if (camera != null)
        //        index = WebCameras.FindIndex(o => o.Name == camera.Name);
        //    CurCamIndex = index;
        //    CurrentCamera = camera;
        //    string log = string.Format("CAM:{0}", index);
        //    Console.WriteLine(log);
        //    TVLog.WriteLine(log);
        //    if (index == -1)
        //        SetDisplayResolution(Resolution.r240P);

        //    return Configuration.Core.bSetVideoDevice(index);
        //}

        //public static void SetDisplayResolution(Resolution rsl)
        //{
        //    try
        //    {
        //        bool support = true;

        //        if (CurCamIndex == -1)
        //        {
        //            CurResolution = "240p";
        //        }
        //        else
        //        {
        //            CameraDevice cam = WebCameras[CurCamIndex];

        //            switch (rsl)
        //            {
        //                case Resolution.NONE:
        //                    CurResolution = "";
        //                    break;
        //                case Resolution.AUTO:
        //                    CurResolution = "AUTO";
        //                    break;
        //                case Resolution.r240P:
        //                    CurResolution = "240p";
        //                    if (cam.CameraResolutions.Where(o => o.Width == 320 & o.Height == 240).Count() == 0)
        //                        support = false;
        //                    break;
        //                case Resolution.r480P:
        //                    CurResolution = "480p";
        //                    if (cam.CameraResolutions.Where(o => o.Width == 640 & o.Height == 480 & o.BitCount == 24).Count() == 0)
        //                        support = false;
        //                    break;
        //                case Resolution.r720P:
        //                    CurResolution = "720p";
        //                    if (cam.CameraResolutions.Where(o => o.Width == 1280 & o.Height == 720 & o.BitCount == 24).Count() == 0)
        //                        support = false;
        //                    break;
        //                case Resolution.r1080P:
        //                    CurResolution = "1080p";
        //                    if (cam.CameraResolutions.Where(o => o.Width == 1920 & o.Height == 1080 & o.BitCount == 24).Count() == 0)
        //                        support = false;
        //                    break;
        //                default:
        //                    break;
        //            }
        //        }

        //        string log = string.Format("RSL:{0} support:{1}", CurResolution, support);
        //        Console.WriteLine(log);
        //        TVLog.WriteLine(log);

        //        if (support)
        //            Configuration.Core.SetVideoProps(CurResolution, 1);
        //    }
        //    catch (Exception ex)
        //    {
        //        string log = "set resolution err :" + ex.Message;
        //        Console.WriteLine(log);
        //        TVLog.WriteLine(log);
        //    }
        //}

        //public static bool SetAudioDevices(AudioDevice record, AudioDevice playback)
        //{
        //    //var tmpmic = RecordDevices.Where(o => o.Name == record.Name).FirstOrDefault();
        //    //var tmpspk = PlaybackDevices.Where(o => o.Name == playback.Name).FirstOrDefault();

        //    int recindex = RecordDevices.FindIndex(o => o.Name == record.Name);
        //    int pbindex = PlaybackDevices.FindIndex(o => o.Name == playback.Name);
        //    pbindex = pbindex == -1 ? 0 : pbindex;
        //    CurrentRecordDevice = record;
        //    CurrentPlaybackDevice = playback;
        //    string log = string.Format("REC:{0} PB:{1}", recindex, pbindex);
        //    Console.WriteLine(log);
        //    TVLog.WriteLine(log);
        //    return Configuration.Core.SetAudioDevice(recindex, pbindex);
        //}

        //public static bool ScreenShare()
        //{
        //    string log = "Screen Share.";
        //    Console.WriteLine(log);
        //    TVLog.WriteLine(log);
        //    return Configuration.Core.bSetVideoDevice(-2);
        //}

        //public static void SetVideoCapture(int index)
        //{
        //    CurCamIndex = index;

        //    if (index != -1 & index != -2)
        //    {
        //        if (WebCameras == null || WebCameras.Count == 0)
        //        {
        //            CurCamIndex = -1;
        //        }
        //    }
        //}

        //public static bool SetVideoDevice()
        //{
        //    return Configuration.Core.bSetVideoDevice(CurCamIndex);
        //}

        //public static void SetSpaker(int index)
        //{
        //    if (!SpeakerErr)
        //    {
        //        CurSpeakerIndex = Math.Max(index, 0);
        //        CurSpeakerIndex = Math.Min(CurSpeakerIndex, TVMixer.Instance.PlaybackDevices.Count - 1);
        //        if (!TVVS.SpeakerErr)
        //            CurrentPlaybackDevice = TVMixer.Instance.PlaybackDevices[CurSpeakerIndex];
        //    }
        //}

        //public static void SetMic(int index)
        //{
        //    if (!MicErr)
        //    {
        //        CurMicIndex = Math.Max(index, 0);
        //        CurMicIndex = Math.Min(CurMicIndex, TVMixer.Instance.RecordDevices.Count - 1);
        //        CurrentRecordDevice = TVMixer.Instance.RecordDevices[CurMicIndex];
        //    }
        //}

        //public static void SetAudioDevice()
        //{
        //    Configuration.Core.SetAudioDevice(CurSpeakerIndex, CurMicIndex);
        //}

        //        public static bool SetCaptures()
        //        {
        //            bool ok = false;
        //            ok = SetVideoDevice();
        //            SetAudioDevice();
        //            SetVideoDeviceRsl();
        //            //SetMicProperty();

        //            string fromMsg = "";
        //            switch (CurResolution)
        //            {
        //                case "AUTO":
        //                    fromMsg = "zwan_switchVideoFormateVGA";
        //                    break;
        //                case "240p":
        //                    fromMsg = "zwan_switchVideoFormateCIF";
        //                    break;
        //                case "480p":
        //                    fromMsg = "zwan_switchVideoFormateVGA";
        //                    break;
        //                case "720p":
        //                    fromMsg = "zwan_switchVideoFormate720P";
        //                    break;
        //                case "1080p":
        //                    fromMsg = "zwan_switchVideoFormate720P";
        //                    break;
        //                default:
        //                    fromMsg = "zwan_switchVideoFormateVGA";
        //                    break;
        //            }

        //            //TVVS.Features_SendMessage(fromMsg);

        //            string log = string.Format(" cam:{0}\r\n spk:{1}\r\n mic:{2}\r\n rsl:{3}", CurCamIndex, CurSpeakerIndex, CurMicIndex, CurResolution);

        //#if DEBUG
        //            Console.WriteLine(log);
        //#endif
        //            TVLog.WriteLine(log);
        //            return ok;
        //        }

        //public static void GetCaptures()
        //{
        //    try
        //    {
        //        //SetMicProperty(true, false, false);
        //        CurrentPlaybackDevice = TVMixer.Instance.DefaultPlaybackDevice;
        //        CurrentRecordDevice = TVMixer.Instance.DefaultRecordDevice;

        //        string audioDeviceLog = "";
        //        audioDeviceLog += "=========================================\r\n";
        //        audioDeviceLog += "Playback Device List:\r\n";
        //        foreach (var item in TVMixer.Instance.PlaybackDevices)
        //        {
        //            audioDeviceLog += item.Name + "\r\n";
        //        }
        //        audioDeviceLog += "Default : " + TVMixer.Instance.DefaultPlaybackDevice + "\r\n";
        //        audioDeviceLog += "Record Device List:\r\n";
        //        foreach (var item in TVMixer.Instance.RecordDevices)
        //        {
        //            audioDeviceLog += item.Name + "\r\n";
        //        }
        //        audioDeviceLog += "Default : " + TVMixer.Instance.DefaultRecordDevice + "\r\n";
        //        audioDeviceLog += "=========================================\r\n";
        //        TVLog.WriteLine(audioDeviceLog);
        //    }
        //    catch (Exception ex)
        //    {
        //        MicErr = true;

        //        TVLog.WriteLine("获取采集设备异常:" + ex.Message);
        //    }
        //}

        /// <summary>
        /// 麦克风属性设置
        /// </summary>
        /// <param name="ec">回声抑制</param>
        /// <param name="ns">噪音消除</param>
        /// <param name="agc">自动增益</param>
        public static void SetMicProperty(bool ec, bool ns, bool agc)
        {
            EC = ec;
            NS = ns;
            AGC = agc;

            sbyte on = 1;
            sbyte off = 0;

            string miclog = string.Format("MicPro: EC.{0} NS.{1} AGC.{2}", EC, NS, AGC);
            Console.WriteLine(miclog);
            TVLog.WriteLine(miclog);
            Configuration.Core.bSetAudioParam(EC ? on : off, NS ? on : off, AGC ? on : off);
        }

        //private static void SetMicProperty()
        //{
        //    string miclog = string.Format("MicPro: EC.{0} NS.{1} AGC.{2}", EC, NS, AGC);
        //    Console.WriteLine(miclog);
        //    TVLog.WriteLine(miclog);
        //    Configuration.Core.bSetAudioParam(EC, NS, AGC);
        //}

        //public static void SetResolution(Resolution rsl)
        //{
        //    switch (rsl)
        //    {
        //        case Resolution.r240P:
        //            CurResolution = "240p";
        //            break;
        //        case Resolution.r480P:
        //            CurResolution = "480p";
        //            break;
        //        case Resolution.r720P:
        //            CurResolution = "720p";
        //            break;
        //        case Resolution.r1080P:
        //            CurResolution = "1080p";
        //            break;
        //        case Resolution.AUTO:
        //            CurResolution = "AUTO";
        //            break;
        //        default:
        //            CurResolution = "AUTO";
        //            break;
        //    }

        //    if (CurCamIndex == -1)
        //        CurResolution = "240p";

        //    //SetVideoDeviceRsl();
        //}

        //public static void SetVideoDeviceRsl()
        //{
        //    //if (CurCamIndex == -1)
        //    //    SetResolution(Resolution.r240P);
        //    Configuration.Core.SetVideoProps(CurResolution, 1);
        //}

        [Obsolete("过时的设备信息获取方法，请参考 UpdateDeviceList ")]
        public static async void UpdateCaptureDevices()
        {
            await Task.Delay(1000);

            TVLog.WriteLine(">>>获取采集设备信息");
            //GetCaptures();
        }

        public static void Dispose()
        {
            if (Configuration.Core != null)
            {

            }
        }
    }
}
